package com.bocomm.tracevisualization.job;

import com.bocomm.tracevisualization.api.entity.*;
import com.bocomm.tracevisualization.api.service.ITraceTargetDataDetailService;
import com.bocomm.tracevisualization.api.service.ITraceTargetDataService;
import com.bocomm.tracevisualization.api.service.ITranslateManagementService;
import com.bocomm.tracevisualization.core.CmdExecutor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Scope("prototype")
@Slf4j
public class MyJob implements Job {

    @Autowired
    ITraceTargetDataService traceTargetDataService;

    @Autowired
    ITraceTargetDataDetailService traceTargetDataDetailService;

    @Autowired
    ITranslateManagementService translateManagementService;

    @Override
    @Transactional
    public void execute(JobExecutionContext context) throws JobExecutionException {
        log.info("调度执行开始！{}",context.getJobDetail().getKey());
        JobDataMap jobDataMap = context.getMergedJobDataMap();
            String terminalIp = (String) jobDataMap.get("terminalIp");
            Double delayThreshold = (Double)jobDataMap.get("delayThreshold");
            Integer timeoutThreshold =(Integer)jobDataMap.get("timeoutThreshold");
        Traceroute traceroute = new Traceroute();
        try {

            CmdExecutor.execTrace(30,3,terminalIp,timeoutThreshold,traceroute);
            Date fireTime = context.getFireTime();
            JobKey key = context.getJobDetail().getKey();
            log.info("fireTime:{}",fireTime);
            postProcessTraceRouteHops(traceroute,delayThreshold,fireTime,key.toString());

        } catch (Exception e) {
            log.error("execTrace error:",e);
        }

        log.info("调度执行开始！{} 完成",context.getJobDetail().getKey());
    }

    private void postProcessTraceRouteHops(Traceroute traceroute, final Double delayThreshold, final Date fireTime, String jobKey) {

        String targetHost = translateManagementService.aliasIp(traceroute.getTargetIp());
        String sourceHost = translateManagementService.aliasIp(traceroute.getSourceIp());
        traceroute.setSourceHost(sourceHost);
        traceroute.setTargetHost(targetHost);

        TraceTargetData traceTargetData = new TraceTargetData(traceroute);

        long time = fireTime.getTime();

        List<TracerouteHop> tracerouteHops = traceroute.getTracerouteHops();
        List<TraceTargetDataDetail> traceTargetDataDetails = tracerouteHops.stream().sorted(Comparator.comparingInt(TracerouteHop::getHopNumber)).map(
                tracerouteHop -> {
                    TraceTargetDataDetail traceTargetDataDetail = new TraceTargetDataDetail(tracerouteHop);
                    traceTargetDataDetail.setSourceIp(traceroute.getSourceIp());
                    traceTargetDataDetail.setSourceHost(sourceHost);
                    traceTargetDataDetail.setTargetHost(translateManagementService.aliasIp(tracerouteHop.getLastTargetIp()));
                    double lastTrtTime = tracerouteHop.getLastTrtTime();
                    if(lastTrtTime>0.0d){
                        traceTargetDataDetail.setTimeOut(lastTrtTime > delayThreshold);
                    }

                    traceTargetDataDetail.setTraceResult(lastTrtTime);
                    traceTargetDataDetail.setTraceTime(time);
                    traceTargetDataDetail.setJobId(jobKey);
                    return traceTargetDataDetail;
                }
        ).collect(Collectors.toList());
        traceTargetData.setTraceTime(time);
        traceTargetData.setJobId(jobKey);
        traceTargetData.setDelayTime(delayThreshold);
        TraceTargetDataDetail traceTargetDataDetail = traceTargetDataDetails.get(traceTargetDataDetails.size() - 1);

        String lastTargetIp = traceTargetDataDetail.getTargetIp();
        String targetIp = traceTargetData.getTargetIp();
        Double traceTime = traceTargetDataDetail.getTraceResult();

        traceTargetData.setSuccess(targetIp.equalsIgnoreCase(lastTargetIp));
        traceTargetData.setTraceResult(traceTime);

        traceTargetDataService.save(traceTargetData);
        traceTargetDataDetailService.saveBatch(traceTargetDataDetails);
    }

}